if Map == nil then
    Map = {}
    Map.__index = Map
end

function Map:new( o )
    o = o or {}
    setmetatable( o, Map )
    return o
end


function Map:Init()
    Map.spawnPosList={}
    Map.runePosList={}
    Map.goldPosList={}
    Map.creepPosList={}
    Map.centerPosList={}
    Map.tpPosList={}
    Map.baseMapSize=1700
    Map.baseMapRang=Map.baseMapSize/2
    Map.bossPos=nil
    Map.bossTp=nil
    local vPos=Entities:FindAllByClassname( "info_player_start_dota" )
    for _, value in pairs(vPos) do
        if string.find(value:GetName(), "info_player")~=nil then
            Map.spawnPosList[value:GetTeam()]=value:GetAbsOrigin()
        end
    end

    local vPos4=Entities:FindAllByClassname( "info_target" )
    for _, value in pairs(vPos4) do
        if string.find(value:GetName(), "info_map_center")~=nil then
            local team=value:GetMoveParent():GetTeam()
            local rune = Entities:FindByClassnameNearest( "dota_item_rune_spawner",value:GetAbsOrigin(),1800)

            if rune~=nil then
                Map.runePosList[team]=rune:GetAbsOrigin()
            end

            local gold = Entities:FindByClassnameNearest( "dota_item_spawner",value:GetAbsOrigin(),1800)
            if gold~=nil then
                Map.goldPosList[team]=gold:GetAbsOrigin()
            end

            local creep = Entities:FindByClassnameNearest( "npc_dota_spawner",value:GetAbsOrigin(),1800)
            if creep~=nil then
                Map.creepPosList[team]=creep:GetAbsOrigin()
            end

            Map.centerPosList[team]=value:GetAbsOrigin()
        elseif string.find(value:GetName(), "boss_spawner")~=nil then
            Map.bossPos=value:GetAbsOrigin()
        end
    end
    SpawnEntityFromTableSynchronous("info_particle_target", {
        origin = Vector(0,0.5,1),
        targetname = "teleport_particle_cp1",
    })
    local vPos5=Entities:FindAllByClassname( "trigger_hero" )
    for _, value in pairs(vPos5) do
        if string.find(value:GetName(), "teleport_trigger")~=nil  then
            if string.find(value:GetName(), "boss")~=nil then
                Map.bossTp=value
                SpawnEntityFromTableSynchronous("info_particle_target", {
                    origin = Vector(0.8,0.25,0.25),
                    targetname = "boss_teleport_particle_cp1",
                })
                Map.bossTp.particle=SpawnEntityFromTableSynchronous("info_particle_system",{
                    origin = value:GetAbsOrigin(),
                    effect_name = ParticleNames.tp,
                    start_active = "1",
                    cpoint1 = "boss_teleport_particle_cp1",
                })
                local scope = value:GetOrCreatePrivateScriptScope()
                scope.OnStartTouch =  function(trigger)
                    print("OnStartTouch Boss tp trigger...")
                    if Map.bossTp.firstActivator~=nil then
                        return
                    end
                    local hero=trigger.activator
                    Map.bossTp.firstActivator=hero
                    Tower:HideBossTower()
                    BossSpawner:StartSpawn(hero)

                    local ability= hero:FindAbilityByName(AbilitiesNames.ability_tp)
                    ability.nextPos=Map.bossPos
                    ability:CastAbility()
                    hero.mapPosIndex=-2
                    MsgUtil:ShowCombat({
                        t="Boss_Area_Enter",
                        player = hero:GetPlayerID()
                    })
                    Map.bossTp:SetAbsOrigin(Vector(0,0,-1000))
                    Map.bossTp.mapPosIndex=nil
                    Map.bossTp.particle:SetAbsOrigin(Vector(0,0,-1000))
                end
                value:RedirectOutput('OnStartTouch', 'OnStartTouch', value)
            else
                SpawnEntityFromTableSynchronous("info_particle_system",{
                    origin = value:GetAbsOrigin(),
                    effect_name = ParticleNames.tp,
                    start_active = "1",
                    cpoint1 = "teleport_particle_cp1",
                })
                Map.tpPosList[value:GetMoveParent():GetTeam()]=value:GetAbsOrigin()
                local scope = value:GetOrCreatePrivateScriptScope()
                scope.OnStartTouch =  function(trigger)
                    --print("OnStartTouch")
                    if trigger.activator.isTp==true then
                        return
                    end
                    local hero=trigger.activator
                    if CalcDistanceBetweenEntityOBB(trigger.caller,hero)~=0 then
                        return
                    end
                    local ability= hero:FindAbilityByName(AbilitiesNames.ability_tp)
                    local index,pos=Hero:GetRandomSpawnPos(hero)
                    ability.nextPos=pos
                    ability:CastAbility()
                    hero.mapPosIndex=index
                end
                value:RedirectOutput('OnStartTouch', 'OnStartTouch', value)
            end
        end
    end
    local vPos6=Entities:FindAllByClassname( "trigger_dota" )
    for _, value in pairs(vPos6) do
        if string.find(value:GetName(), "water_trigger")~=nil then
            local scope = value:GetOrCreatePrivateScriptScope()
            scope.OnStartTouch =  function(trigger)
                print("OnStartTouch water_trigger")
                trigger.activator:AddNewModifier(trigger.activator,nil,AbilitiesNames.modifier_water_debuff,{colorX=0.2,colorY=0,colorZ=0.05})
            end
            scope.OnEndTouch =  function(trigger)
                print("OnEndTouch water_trigger")
                if trigger.activator~=nil then
                    trigger.activator:RemoveModifierByName(AbilitiesNames.modifier_water_debuff)
                end
            end
            value:RedirectOutput('OnEndTouch', 'OnEndTouch', value)
            value:RedirectOutput('OnStartTouch', 'OnStartTouch', value)
        end
    end

end
